import os, sys, time

from urllib2 import build_opener, HTTPCookieProcessor, HTTPRedirectHandler, Request
from urllib import urlencode
from urlparse import urljoin
import db, utils

try:
	from ConfigParser import SafeConfigParser as ConfigParser
except ImportError:
	from ConfigParser import ConfigParser
CONFIG_FILE = os.path.join(os.environ['HOME'], '.wjs.ini')
config = ConfigParser()
config.read(CONFIG_FILE)

class AuctionHouse:
	def __init__(self, config):
		self.opener = build_opener()
		self.opener.add_handler(HTTPCookieProcessor())
		self.opener.add_handler(HTTPRedirectHandler())

		self.root = config.get("wow-armory", "ah-url")
		self.loginParams = {
			"accountName": config.get("wow-armory", "login"),
			"password": config.get("wow-armory", "password")
		}
		self.prev_query_time = None
		self.wait_time = 1

	def getJsonData(self, response):
		data = utils.GetJsonData(response)
		error = data.get('error')
		if error:
			raise RuntimeError("AH Error(%d): %s" % (error['code'], error['message']))
		return data

	def connect(self):
		# Get starting point
		request = Request(self.root, None, utils.DEFAULT_HEADER)
		response = self.opener.open(request)
		target = utils.GetFirstFormTarget(response.read())
		url = urljoin(response.geturl(), target)
		# login url
		request = utils.MakeDataRequest(url, self.loginParams)
		response = self.opener.open(request)
		target = utils.GetFirstFormTarget(response.read())
		if target.startswith("authenticator.html"):
			url = urljoin(response.geturl(), target)
			code = raw_input("Authenticator code: ")
			request = utils.MakeDataRequest(url, {"authValue": code})
			response = self.opener.open(request)

	def query(self, base, **kwArgs):
		if self.wait_time and self.prev_query_time:
			curr_time = time.time()
			delta = curr_time - self.prev_query_time
			sleep_time = self.wait_time - delta
			if sleep_time > 0:
				time.sleep(sleep_time)
		self.prev_query_time = time.time()
		url = urljoin(self.root, base) + "?" + urlencode(kwArgs)
		request = Request(url, None, utils.DEFAULT_HEADER)
		response = self.opener.open(request)
		return self.getJsonData(response.read())

	def getCharInfo(self):
		data = self.query("money.json")
		self.money = data["money"]
		char = data["command"]
		self.name = char["cn"]
		self.realm = char["r"]
		if char["f"] == 0:
			faction = "Alliance"
		else:
			faction = "Horde"
		gold = self.money / 10000
		silver = (self.money / 100) % 100
		copper = self.money % 100

		print "%s (%s-%s) has %dg %ds %dc" % (self.name, self.realm, faction, gold, silver, copper)

	def getItemObject(self, data):
		try:
			item = db.Item.byItemId(data["id"])
		except db.SQLObjectNotFound:
			item = db.Item(itemId = data["id"],
				name = data["n"], itemLevel = data["ilvl"],
				quality = data["qual"],
				icon = data["icon"])
		return item

	def getAuctionObject(self, data):
		try:
			auction = db.Auction.byAuctionId(data["auc"])
		except db.SQLObjectNotFound:
			auction = db.Auction(auctionId = data["auc"],
				seller = data["seller"],
				item = self.getItemObject(data),
				seed = data.get("seed"),
				quantity = data["quan"],
				buy = data.get("buy"),
				ppuBuy = data.get("ppuBuy"),
				)
		auction.set(bid = data["bid"], ppuBid = data.get("ppuBid"))
		return auction

	def search(self, params):
		p = {
			'filterId': params.filterId,
			'pageSize': 200,
		}
		if params.minLvl:
			p['minLvl'] = params.minLvl
		if params.maxLvl:
			p['maxLvl'] = params.maxLvl
		if params.qual:
			p['qual'] = params.qual
		while True:
			data = self.query("search.json", **p)
			result = data.get('auctionSearch')
			if result:
				total = result['total']
				start = result['start']
				end = result['end']
				print "%s : %d-%d/%d" % (params.filterId, start, end, total)
				if total == 200:
					print "WARNING: Too many results for %s" % params.filterId
				#~ assert total < 200
				auctions = result.get('auctions')
				if auctions:
					for data in auctions:
						self.getAuctionObject(data)
				if end >= total:
					break
				p['start'] = end
	def searchAll(self):
		for params in db.SearchParam.select(db.SearchParam.q.active == True):
			self.search(params)

if __name__ == '__main__':
	db.init(config.get("dsn", "auctions"))
	ah = AuctionHouse(config)
	ah.connect()
	ah.getCharInfo()
	ah.searchAll()
